package base.thread_demo.demo08;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Resource中写法逻辑不合理演示
 * 不合理因素如下:
 * 1.run()中不需要while(true),自己就可以实现无线循环下去,只要消费者线程确保能够唤醒该生产者线程
 * 2.一个线程调用任务一次,却无限循环执行生产动作,没有将无限生产的动作交由任务来控制
 */
public class ProblemResource {

    public static void main(String[] args) {
        Resource r = new ProblemResource().new Resource("烤鸭");

        Run1 t1 = new ProblemResource().new Run1(r);
        Run2 t2 = new ProblemResource().new Run2(r);
        new Thread(t1, "t1").start();
        new Thread(t2, "t2").start();
    }

    class Run1 implements Runnable{
        private Resource r;
        public Run1(Resource r){
            this.r = r;
        }
        @Override
        public void run() {
            r.set(r.getName());
        }
    }
    class Run2 implements Runnable{
        private Resource r;
        public Run2(Resource r){
            this.r = r;
        }
        @Override
        public void run() {
            r.get();
        }
    }

    class Resource{
        private final Logger log = LoggerFactory.getLogger(Resource.class);

        private String name;
        private int count = 1;
        private boolean flag = false;

        public Resource(String name){
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public synchronized void set(String name) {
            while (!flag) {
                this.name = name + count++;
                this.flag = true;
                log.info("------------->{} 生产了 {}", Thread.currentThread().getName(), this.name);
                this.notifyAll();
                try {
                    this.wait();//唯一醒过来的方式就是被唤醒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public synchronized void get() {
            while (flag) {
                log.info("{} 消费了 {}", Thread.currentThread().getName(), this.name);
                this.flag = false;
                this.notifyAll();
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
